import React, { useCallback, useEffect, forwardRef, useImperativeHandle, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { drawBuffer, VSHADER_SOURCE, FSHADER_SOURCE } from './bvf';
import { initShaders } from './shader';
import styles from './index.module.less';

const Index = forwardRef((props, ref) => {
  const { className } = props;

  useImperativeHandle(ref, () => ({
    drawArray: (array) => {
      if (array) {
        drawDance(array);
      }
    },
  }));

  useEffect(() => {
    setInterval(() => {
      const arr = [];
      for (let i = 0; i < 48; i += 1) {
        arr[i] = Math.random() * 255;
      }
      drawDance(arr);
    }, 1000);
  }, []);

  const options = useRef({
    rows: 18,
    cols: 46,
    minWidth: 480,
    colors: [
      '#0A77B4',
      '#1084B7',
      '#1691BB',
      '#1C9EBF',
      '#21AAC2',
      '#27B7C6',
      '#2DC4CA',
      '#33D1CD',
      '#39DED1',
      '#3CE5D3',
      '#3CE5D3',
      '#3CE5D3',
      '#3CE5D3',
      '#3CE5D3',
      '#3CE5D3',
      '#3CE5D3',
      '#3BE4D2',
      '#3BE4D2',
    ],
    emptyColor: '#3CE5D310',
  }).current;

  const canRef = useRef(null);
  const containeRef = useRef(null);

  const [drawingSize, setDrawingSize] = useState({ width: 300, height: 300 });

  window.console.log(drawingSize);

  const onResize = useCallback(() => {
    const { offsetHeight: height, offsetWidth: width } = containeRef.current || {};

    setDrawingSize({ width, height });

    const gl = canRef.current.getContext('webgl');
    if (gl) {
      const aResolution = gl.getAttribLocation(gl.program, 'a_Resolution');
      gl.vertexAttrib2f(aResolution, width, height);
    }

    options.cols = 48;
    options.blockWidth = Math.max(width / options.cols, 10);
    options.rows = Math.round(height / options.blockWidth);
    options.blockHeight = Math.max(height / options.rows, 10);
    options.gap =
      options.blockWidth < 10
        ? 1
        : options.blockWidth >= 10 && options.blockWidth <= 30
        ? options.blockWidth / 5 - 1
        : 5;
    options.innerRect = { w: options.blockWidth - options.gap * 2, h: options.blockHeight - options.gap * 2 };
  }, []);

  useEffect(() => {
    const ro = new ResizeObserver(onResize);
    containeRef.current && ro.observe(containeRef.current);
    return () => {
      containeRef.current && ro.unobserve(containeRef.current);
      ro.disconnect();
    };
  }, []);

  useEffect(() => {
    const gl = canRef.current.getContext('webgl');
    if (gl) {
      initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE);
    }
  }, []);

  const drawDance = (data) => {
    const { width, height } = canRef.current || {};
    const {
      cols,
      rows,
      gap,
      blockWidth,
      blockHeight,
      innerRect: { w, h },
    } = options;
    const step = parseInt(data.length / cols, 10);
    const ps = [];
    window.console.log(ps, rows, options);
    for (let i = 0; i < 48; i += 1) {
      const d = data[i * step];
      const m = parseInt((d / 256) * 18, 10);
      for (let j = 0; j < rows; j += 1) {
        const p = { x: i * blockWidth + gap, y: height - blockHeight * j - blockHeight + gap };
        ps.push(p.x - gap + blockWidth / 2);
        ps.push(height - p.y - blockHeight / 2 + gap);
        const size = { w, h };
        const color = j >= m ? options.emptyColor : options.colors[Math.min(j, options.colors.length)];
      }
    }
    const gl = canRef.current.getContext('webgl');
    if (gl) {
      drawBuffer(gl, ps, 'a_Position');
    }
  };

  return (
    <div ref={containeRef} className={classnames(styles.root, className)} style={{ minWidth: options.minWidth }}>
      <canvas ref={canRef} {...drawingSize} style={{ ...drawingSize }} width={1020} height={483}>
        Your browser does not support the canvas element.
      </canvas>
    </div>
  );
});

Index.defaultProps = {
  className: null,
};

Index.propTypes = {
  className: PropTypes.any,
};

export default Index;
